package com.lk.security.authentication.mobile;

import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

/**
 * @description: 手机认证处理提供者
 * @author: Aspirin
 * @create: 2020-05-31 10:18
 */
public class MobileAuthenticationProvider implements AuthenticationProvider {

  private UserDetailsService userDetailsService;

  public void setUserDetailsService(UserDetailsService userDetailsService) {
    this.userDetailsService = userDetailsService;
  }

  /**
   * 认证处理： 1. 通过手机号码 查询用户信息(userDetailsService实现) 2. 当查询到用户信息，则认为认证通过，封装Authentication对象
   *
   * @param authentication 认证信息
   * @return Authentication
   * @throws AuthenticationException AuthenticationException
   */
  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    MobileAuthenticationToken mobileAuthenticationToken =
        (MobileAuthenticationToken) authentication;
    // 获取手机号码
    String mobile = (String) mobileAuthenticationToken.getPrincipal();
    // 通过手机号码查询用户信息(userDetailService实现)
    UserDetails userDetails = userDetailsService.loadUserByUsername(mobile);
    // 未查询到用户信息
    if (userDetails == null) {
      throw new AuthenticationServiceException("该手机号未注册");
    }

    // 封装到 MobileAuthenticationToken
    MobileAuthenticationToken authenticationToken =
        new MobileAuthenticationToken(userDetails, userDetails.getAuthorities());
    authenticationToken.setDetails(mobileAuthenticationToken.getDetails());

    return authenticationToken;
  }

  /**
   * 通过这个方法，来选择对应的Provider，即选择MobileAuthenticationProvider
   *
   * @param authentication 认证信息
   * @return true调用这个Provider
   */
  @Override
  public boolean supports(Class<?> authentication) {
    return MobileAuthenticationToken.class.isAssignableFrom(authentication);
  }
}
